import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import axios from 'axios'
import { Modal } from 'ant-design-vue'
import { h } from 'vue'
import { ExclamationCircleFilled } from '@ant-design/icons-vue'
import { AxiosLoading } from './loading'
import { AUTH_HEADER_KEY, useAuthorization } from '~/composables/authorization'
import { ContentTypeEnum, RequestEnum } from '~#/http-enum'
import router from '~/router'
import warnTipIcon from '~/assets/images/warn_tip.png'

export interface ResponseBody<T = any> {
  code: number
  data?: T
  msg: string
}

export interface RequestConfigExtra {
  token?: boolean
  customDev?: boolean
  loading?: boolean
}
const instance: AxiosInstance = axios.create({
  // 生产环境使用相对路径（空字符串），因为 API 路径已经包含 /api 前缀
  // 开发环境使用完整后端地址
  baseURL: import.meta.env.PROD
    ? ''
    : (import.meta.env.VITE_APP_BASE_API ?? 'http://127.0.0.1:5000'),
  timeout: 60000,
  headers: { 'Content-Type': ContentTypeEnum.JSON },
})
const axiosLoading = new AxiosLoading()
async function requestHandler(config: InternalAxiosRequestConfig & RequestConfigExtra): Promise<InternalAxiosRequestConfig> {
  // 处理请求前的url
  if (
    import.meta.env.DEV
      && config.customDev
  ) {
    //  替换url的请求前缀baseUrl，直接使用后端地址
    config.baseURL = 'http://127.0.0.1:5000'
  }
  const token = useAuthorization()

  if (token.value && config.token !== false) {
    const headerValue = token.value.startsWith('Bearer ')
      ? token.value
      : `Bearer ${token.value}`
    // 始终使用标准的 Authorization 作为请求头名称
    config.headers.set(AUTH_HEADER_KEY, headerValue)
  }

  // 增加多语言的配置
  const { locale } = useI18nLocale()
  config.headers.set('Accept-Language', locale.value ?? 'zh-CN')
  if (config.loading)
    axiosLoading.addLoading()
  return config
}

function responseHandler(response: any): ResponseBody<any> | AxiosResponse<any> | Promise<any> | any {
  // 直接返回响应数据，因为后端直接返回业务数据
  return response.data
}

function errorHandler(error: AxiosError): Promise<any> {
  const token = useAuthorization()
  if (error.response) {
    const responseData = error.response.data as any

    // 后端返回格式: { code: 40002, message: "图片验证码错误或已过期", data: null }
    if (responseData && typeof responseData === 'object' && responseData.code !== undefined) {
      // 业务错误：code !== 0
      if (responseData.code !== 0) {
        const errorMessage = responseData.message || responseData.msg || '请求失败'
        Modal.info({
          title: '',
          content: h('div', { style: 'font-size:16px; line-height:24px; color:#333;' }, errorMessage),
          // 自定义图标：使用 img 标签
          icon: h('img', {
            src: warnTipIcon, // 图片资源（导入的变量）
            style: {
              width: '40px', // 根据需要调整大小
              height: '36px',
              marginRight: '8px', // 与文字保持间距（默认图标有此间距）
              // 如果图片有透明背景，可无需额外调整
            },
          }),
          okText: '确定',
          okButtonProps: { style: { backgroundColor: '#da1211', border: 'none', borderRadius: '0' } } as any,
          centered: true,
        })
        // 返回一个特殊的错误对象，包含业务错误信息
        const customError = new Error(errorMessage) as any
        customError.isBusinessError = true
        customError.code = responseData.code
        customError.data = responseData.data
        return Promise.reject(customError)
      }
    }

    // HTTP状态码错误处理
    const { data, status, statusText } = error.response as AxiosResponse<ResponseBody>
    if (status === 401) {
      Modal.info({
        title: '提示',
        content: h('div', { style: 'font-size:16px; line-height:24px; color:#333;' }, data?.msg || statusText || '401 未授权'),
        icon: h(ExclamationCircleFilled, { style: 'color:#00BAC7;' }),
        okText: '确定',
        okButtonProps: { style: { backgroundColor: '#00BAC7', border: 'none', borderRadius: '0' } } as any,
        centered: true,
      })
      /**
       * 这里处理清空用户信息和token的逻辑，后续扩展
       */
      token.value = null
      router
        .push({
          path: '/login',
          query: {
            redirect: router.currentRoute.value.fullPath,
          },
        })
        .then(() => {})
    }
    else if (status === 403) {
      Modal.info({
        title: '提示',
        content: h('div', { style: 'font-size:16px; line-height:24px; color:#333;' }, data?.msg || statusText || '403 禁止访问'),
        icon: h(ExclamationCircleFilled, { style: 'color:#00BAC7;' }),
        okText: '确定',
        okButtonProps: { style: { backgroundColor: '#da1211', border: 'none', borderRadius: '0' } } as any,
        centered: true,
      })
    }
    else if (status === 500) {
      Modal.info({
        title: '提示',
        content: h('div', { style: 'font-size:16px; line-height:24px; color:#333;' }, data?.msg || statusText || '500 服务器错误'),
        icon: h(ExclamationCircleFilled, { style: 'color:#00BAC7;' }),
        okText: '确定',
        okButtonProps: { style: { backgroundColor: '#00BAC7', border: 'none', borderRadius: '0' } } as any,
        centered: true,
      })
    }
    else {
      Modal.info({
        title: '提示',
        content: h('div', { style: 'font-size:16px; line-height:24px; color:#333;' }, data?.msg || statusText || '服务错误'),
        icon: h(ExclamationCircleFilled, { style: 'color:#00BAC7;' }),
        okText: '确定',
        okButtonProps: { style: { backgroundColor: '#00BAC7', border: 'none', borderRadius: '0' } } as any,
        centered: true,
      })
    }
  }
  return Promise.reject(error)
}
interface AxiosOptions<T> {
  url: string
  params?: T
  data?: T
}
instance.interceptors.request.use(requestHandler)

instance.interceptors.response.use(responseHandler, errorHandler)

export default instance
function instancePromise<R = any, T = any>(options: AxiosOptions<T> & RequestConfigExtra): Promise<ResponseBody<R>> {
  const { loading } = options
  return new Promise((resolve, reject) => {
    instance.request(options).then((res) => {
      resolve(res as any)
    }).catch((e: Error | AxiosError) => {
      reject(e)
    })
      .finally(() => {
        if (loading)
          axiosLoading.closeLoading()
      })
  })
}
export function useGet< R = any, T = any>(url: string, params?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    params,
    method: RequestEnum.GET,
    ...config,
  }
  return instancePromise< R, T >(options)
}

export function usePost< R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.POST,
    ...config,
  }
  return instancePromise< R, T >(options)
}

export function usePut< R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.PUT,
    ...config,
  }
  return instancePromise<R, T>(options)
}

export function useDelete< R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.DELETE,
    ...config,
  }
  return instancePromise<R, T>(options)
}
